package rs.udd.service.util;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.multipart.MultipartFile;

import rs.udd.constants.GeneralConstants;
import rs.udd.exceptions.UddException;

public class FileUtil {
	
	private static final Logger LOGGER = LogManager.getLogger(FileUtil.class);

	public enum FileTypes {
		CV,
		ADVERT
	}

	// this private constructor prevents this class from instantiation
	private FileUtil() {
	}
	
	public static String handleFileChangeUpload(MultipartFile file, Long uploaderId, FileTypes type, boolean deleteOld) throws UddException {

		try {
			// Creating the directory to store file
			String folderPath = FileUtil.getUserFolderPath(uploaderId, type);
			File dir = new File(folderPath);
			if (!dir.exists())
				dir.mkdirs();

			if (deleteOld) {
				FileUtils.cleanDirectory(dir);
			}

			// Create the file on server
			String filePath = FileUtil.getFilePath(dir, file);
			File serverFile = new File(filePath);
			BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(serverFile));
			stream.write(file.getBytes());
			stream.close();

			return filePath;

		} catch (Exception e) {
			LOGGER.error(e);
			throw new UddException("Error while saving file", e);
		}
	}

	public static String handleFileUpload(MultipartFile file, Long uploaderId, FileTypes type) throws UddException {
		return FileUtil.handleFileChangeUpload(file, uploaderId, type, true);
	}
	
	public static void cleanFile(File file) throws IOException {
		FileUtils.deleteQuietly(file);
	}
	
	public static void cleanFile(String filePath) throws IOException {
		File file = new File(filePath);
		FileUtil.cleanFile(file);
	}
	
	public static void cleanDirectory(String path) throws IOException {
		File dir = new File(path);
		FileUtil.cleanDirectory(dir);
	}
	
	public static void cleanDirectory(File dir) throws IOException {
		FileUtils.cleanDirectory(dir);
	}

	public static String getUserFolderPath(Long uploaderId, FileTypes type) {
		String rootPath = FileUtil.getRootPath();
		String folderPath = rootPath + File.separator + GeneralConstants.SAVED_FILES + File.separator + type.name();
		String userPath = folderPath + File.separator + Long.toString(uploaderId);

		return userPath;
	}
	
	public static String getFolderPathForAdvert(String uploader, FileTypes type) throws IOException {
		String rootPath = FileUtil.getRootPath();
		String folderPath = rootPath + File.separator + GeneralConstants.SAVED_FILES + File.separator + type.name() + File.separator + uploader + File.separator;
		
		File dir = new File(folderPath);
		if (!dir.exists()) {
			dir.mkdirs();
		}
		
		return folderPath;
	}
	
	public static String getIndicesPath() {
		String rootPath = FileUtil.getRootPath();
		String indicesPath = rootPath + File.separator + GeneralConstants.INDICES_FOLDER;
				
		File dir = new File(indicesPath);
		if (!dir.exists())
			dir.mkdirs();
		
		return indicesPath;
	}
	
	public static String getRootPath() {
		String rootPath = System.getProperty(GeneralConstants.CATALINA_HOME);
		if (StringUtils.isEmpty(rootPath))	// if application is not run in server environment, catalina.home will return null. So, this is fall back solution.
			rootPath = FileUtil.getDesktopPath();
		
		rootPath += "/udd_files";
		return rootPath;
	}

	private static String getDesktopPath() {
		String userHome = System.getProperty(GeneralConstants.USER_HOME);
		String desktopPath = userHome + File.separator + "Desktop";
		return desktopPath;
	}
	
	private static String getFilePath(File dir, MultipartFile file) {
		String filePath = dir.getAbsolutePath() + File.separator + file.getOriginalFilename();
		return filePath;
	}

	public static File getFileFromPath(String filePath) {
		if (StringUtils.isEmpty(filePath)) {
			throw new IllegalArgumentException("File path must not be null or empty");
		}
		
		return new File(filePath);
	}
	
	private static final String SPLIT_BY_FILE_BASE_AND_FILE_EXTENSION = "\\.(?=[^\\.]+$)";
	public static String generateFileName(String filePath) {
		String[] tokens = filePath.split(SPLIT_BY_FILE_BASE_AND_FILE_EXTENSION);
		String fileNameBase = tokens[0];
		String fileExtension = tokens[1];
		
		long timestamp = System.currentTimeMillis();
		String newFilePath = fileNameBase + "_" + timestamp + "." + fileExtension;
		return newFilePath;
	}
	
}
